<template>
  <view class="tree-node">
    <view class="node-content" :class="{ 'has-children': hasChildren }">
      <view class="expand-icon" v-if="hasChildren" @tap.stop="handleToggle">
        <uni-icons :type="isExpanded ? 'bottom' : 'right'" size="14" color="#909399"></uni-icons>
      </view>
      <view class="placeholder" v-else></view>

      <view class="checkbox" @tap.stop="handleSelect">
        <uni-icons
          :type="isSelected ? 'checkbox-filled' : 'square'"
          size="16"
          :color="isSelected ? '#409eff' : '#dcdfe6'"
        ></uni-icons>
      </view>

      <text class="node-label" @tap.stop="handleSelect">{{ node.label }}</text>
    </view>

    <view class="children" v-if="hasChildren && isExpanded">
      <xlam-tree-node
        v-for="child in node.children"
        :key="child.id"
        :node="child"
        :selected="selected"
        :expanded="expanded"
        :checkStrictly="checkStrictly"
        @select="handleChildSelect"
        @toggle="handleChildToggle"
      />
    </view>
  </view>
</template>

<script>
export default {
  name: 'xlam-tree-node',
  props: {
    node: {
      type: Object,
      required: true
    },
    selected: {
      type: Array,
      default: () => []
    },
    expanded: {
      type: Set,
      default: () => new Set()
    },
    checkStrictly: {
      type: Boolean,
      default: true
    }
  },
  computed: {
    hasChildren() {
      return this.node.children && this.node.children.length > 0
    },
    isSelected() {
      return this.selected.includes(this.node.id)
    },
    isExpanded() {
      return this.expanded.has(this.node.id)
    },
    allChildrenIds() {
      const ids = []
      const getIds = (node) => {
        if (node.children) {
          node.children.forEach(child => {
            ids.push(child.id)
            getIds(child)
          })
        }
      }
      getIds(this.node)
      return ids
    }
  },
  methods: {
    handleSelect() {
      this.$emit('select', {
        id: this.node.id,
        type: this.isSelected ? 'unselect' : 'select',
        children: this.checkStrictly ? this.allChildrenIds : []
      })
    },
    handleToggle() {
      this.$emit('toggle', this.node.id)
    },
    handleChildSelect(event) {
      this.$emit('select', event)
    },
    handleChildToggle(nodeId) {
      this.$emit('toggle', nodeId)
    }
  }
}
</script>

<style lang="scss">
.tree-node {
  .node-content {
    display: flex;
    align-items: center;
    padding: 16rpx 0;
    transition: all 0.3s;

    &:active {
      background-color: #f5f7fa;
    }

    &.has-children {
      cursor: pointer;
    }

    .expand-icon, .placeholder {
      width: 40rpx;
      height: 40rpx;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .checkbox {
      margin: 0 16rpx;
      display: flex;
      align-items: center;
    }

    .node-label {
      flex: 1;
      font-size: 28rpx;
      color: #606266;
      transition: color 0.3s;

      &:active {
        color: #409eff;
      }
    }
  }

  .children {
    padding-left: 56rpx;
    position: relative;

    &::before {
      content: '';
      position: absolute;
      left: 20rpx;
      top: 0;
      bottom: 0;
      width: 2rpx;
      background-color: #f0f2f5;
    }
  }
}
</style>